<template>
	<view class="slider-box-view"
	:style="[{'width':WidthValue+'px'},{'height':sliderboxViewHeight+'px'}]"
	ref="slider" id="slider" 
	@touchstart.stop="onBlock_TouchStart"
	@touchmove.stop.prevent="onBlock_TouchMove" 
	@touchend.stop="onBlock_TouchEnd"
	@click.stop="onClick_SliderTouch">
		<!-- 纯手工制作进度条 -->
		<view class="slider-box flex"
		:style="[{'width':WidthValue+'px'},{'height':blockBoxHeight+'px'}]">
			<!-- 已缓冲进度[副进度] 大于1才显示，这样不是视频进度条的时候，就不显示 -->
			<view v-if="sliderValueBfb>=1" class="left-slider-huanchong"
			:style="[{'width':WidthValue+'px'},{'height':sliderHeight+'px'},
			{'background-color':'rgba(255,255,255,0)'}]">
				<view class="slider-huanchong"
				:style="[{'width':leftWidthBfb+'px'},{'height':sliderHeight+'px'},
				{'background-color':huanchongColor}]"
				></view>
				<view class="flex1"></view>
			</view>
			<!-- 当前进度[主进度] -->
			<view class="left-slider flex" :style="[{'width':leftWidth+'px'},{'height':sliderHeight+'px'}]">
				<view class="left"  :style="[{'height':sliderHeight+'px'},{'background-color':activeColor},{'background-image':activeBackgroundImage}]"></view>
				<!-- 圆点指示器 2代 -->
				<view v-if="false" class="block-box-line"></view>
			</view>
			<!-- 总进度 -->
			<view class="right-slider flex" :style="[{'width':Number(WidthValue-leftWidth)+'px'},{'height':sliderHeight+'px'},{'border-radius':Number(sliderHeight/2)+'px'}]">
				<view class="right"  :style="[{'height':sliderHeight+'px'},{'background-color':backgroundColor}]"></view>
			</view>
			<!-- 圆点指示器 距离右边再减去自身宽度8px,这里必须让他>=0，不能变成负的，否则小圆点会不见 -->
			<view v-if="disabled==false" class="block-box" :style="[{'left':Number(leftWidth-blockBoxWidth)>=0?Number(leftWidth-blockBoxWidth)+'px':0+'px'},
			{'width':blockBoxWidth+'px'},{'height':blockBoxHeight+'px'},{'border-radius':blockBoxBorderRadius+'px'},{'background-color':blockColor}]"
			></view>
			<!-- @touchstart="onBlock_TouchStart"
			@touchmove.stop.prevent="onBlock_TouchMove" 
			@touchend="onBlock_TouchEnd" -->
			<!-- <view else class="block-box" :style="[{'left':0+'px'}]"></view> -->
		</view>
		<!-- 
			※ ps: 当前版本已是3.3.4或者以上版本。v-if=false将官方进度条去除，不渲染。
			※（自定义的进度条目前没有测试微信小程序，h5、app-vue、app-nvue已测试）
			※ 将在3.3.4版本废弃使用官方进度条的拖动触发事件，暂时先不删除如下代码。
			ps1:将官方的slider变成透明的，然后absoltue定位上来
			ps2:这样就可以实现使用自定义的slider滑块进度条
			ps3:返回还能触发官方的进度条事件，这样就不需要自己去
			ps4:写“手指触摸开始,手指拖动,手指触摸结束”的事件去计算
			ps5:进度条位置，而只需要简单的计算每1进度=多少px就OK了
			1. @change 完成一次拖动后触发的事件，event.detail = {value: value}
			2. @changing 拖动过程中触发的事件，event.detail = {value: value}
		-->
		<!-- slider进度条 -->
		<slider v-if="false" style="opacity: 0;"
		:style="{'width':WidthValue+'px'}"
		class="slider" :min="min" :max="max" :step="step"
		:disabled="disabled" :value="value"
		:activeColor="activeColor" :backgroundColor="backgroundColor"
		:block-size="sliderboxViewHeight" :block-color="blockColor"
		:show-value="showValue" @changing.stop="changing"
		@change="change"/>
		
		<!-- platform_mobile!=='ios' -->
		
		
	</view>
</template>

<script>
	let dom;
	// #ifdef APP-NVUE
	dom = weex.requireModule('dom')
	// #endif
	
	let sdilderPos = {}; //传递参数
	let sliderWidth = 0; //总宽度
	let sliderLeft = 0; //左边
	let dragVal = 0; //点击或拖动计算后的进度条值
	let timeOutEvent = 1; //是单击还是触摸移动了 1单击 0移动
	let init_timer = null; //获取进度条dom节点的定时器id
	export default {
		name:"FatFatMeng-slider",
		props:{
			// 最小值
			min:{
				type:Number,
				default:0
			},
			// 最大值
			max:{
				type:Number,
				default:100//默认,根据时长进行修改
			},
			// 步长，取值必须大于 0，并且可被(max - min)整除
			step:{
				type:Number,
				default:1
			},
			// 是否禁用
			disabled:{
				type:Boolean,
				default:false
			},
			// 当前取值(当前进度)
			value:{
				type:Number,
				default:0
			},
			// [2选1]滑块左侧已选择部分的线条颜色
			activeColor:{
				type:String,
				default:'#00d0d3'
			},
			// [2选1]滑块左侧已选择部分的线条颜色(线性渐变色)
			activeBackgroundImage:{
				type:String,
				default:''
			},
			// 滑块右侧背景条的颜色
			backgroundColor:{
				type:String,
				default:'rgba(255, 255, 255, 0.35)'
			},
			// (小圆点)滑块的大小，取值范围为 12 - 28
			blockSize:{
				type:Number,
				default:14
			},
			// (小圆点)滑块的颜色
			blockColor:{
				type:String,
				default:'#00f8ff'
			},
			// 是否显示当前 value
			showValue:{
				type:Boolean,
				default:false
			},
			// 滑块的总长度
			Width:{
				type:Number,
				default:0
			},
			// 已缓冲的进度
			sliderValueBfb:{
				type:Number,
				default:0
			},
			// 滑块左侧已缓冲部分的线条颜色
			huanchongColor:{
				type:String,
				default:'rgba(255,255,255,0.55)'//原来的颜色#00d0d3
			},
			// 滑块盒子的高度,盒子高度不是进度条高度
			// 盒子是透明的，主要用于优化拖动优化，
			// 受击范文更大，体验更好
			sliderboxViewHeight:{
				type:Number,
				default:30
			},
			// 圆点指示器的宽度[新增]
			blockBoxWidth:{
				type:Number,
				default:8//以px为参考单位
			},
			// 圆点指示器的高度[新增]
			blockBoxHeight:{
				type:Number,
				default:8//以px参考单位
			},
			// 圆点指示器的圆角[新增]
			blockBoxBorderRadius:{
				type:Number,
				default:4//以px参考单位
			},
			// 进度条高度
			sliderHeight:{
				type:Number,
				default:2//以px参考单位
			},
			// 客户端平台
			platform_mobile:{
				type:String,
				default:''//android,ios,mac,windows,linux
			},
			// show (外层的控制面板显隐转态)
			show:{
				type:Boolean,
				default:false
			}
		},
		data() {
			return {
				// Slider总宽度
				WidthValue: this.Width,
				
				//leftWidth: this.value,//当前进度
				// 3.5.1 修复进度条达到100值的时候，当退出或进入非/全屏，左边的进度条会出现位置不对，原因就是value值是100导致的，而页面上是用px距离计算的。
				leftWidth: this.value==100 ? this.Width : 0,//当前进度
				leftWidthBfb: this.sliderValueBfb,//已缓冲完成的进度(百分比)
				
				// 触摸开始时记录当前进度（进度条左边已选择的部分）
				oldLeftWidth: 0,
				// 触摸开始时的X坐标
				oldToucesX: 0,
				// 触摸移动时计算后的当前进度（进度条左边已选择的部分）
				newLeftWidth: 0,
				// 位移的偏移量
				x: 0,
				// 是否正在触摸过程中，用于标记动画类是否添加或移除
				touching: false,
				posVal: 0, //进度条值（完成触摸移动后计算的值）
			};
		},
		watch:{
			Width:{
				handler(newWidth,oldWidth){
					this.WidthValue = newWidth
				},
				immediate: true,//普通监听（可监听到第一次绑定的变化）
			},
			value:function(e){
				//console.log('当前进度')
				//console.log(e)
				let value = e
				// 还原入口参数
				let event = {detail:{value}}
				//console.log(event)
				// 执行更新进度
				this.toUpdate(event)
			},
			show:{
				handler(newShow,oldShow){
					if (newShow == true){
						// 初始化任务
						this.Init()
					}
				},
				immediate: true,
			}
		},
		async created() {
			//console.log("滑块的总长度")
			//console.log(this.Width)

			// 设置进度条宽度
			this.WidthValue = this.Width
		},
		mounted() {
			// 初始化任务
			//this.Init()
		},
		methods:{
			// 初始化任务
			Init(){
				// 延时500毫秒后再获取
				init_timer = setTimeout(() =>{
					// 更新滑块尺寸信息
					this.getSliderRect().then((res) => {
						if (res.width != 0) {
							sliderWidth = res.width
						}
						if (res.left != 0) {
							sliderLeft = res.left
						}
						// #ifdef APP-PLUS-NVUE
						//this.WidthValue = res.width
						// #endif
						console.log(sliderWidth,sliderLeft)
						// 判断进度条的值是否为100
						if (this.value==100){
							this.leftWidth = sliderWidth
						}
						// 消除定时器
						clearTimeout(init_timer)
					});
				},400)
			},
			// 获取节点信息
			// 获取slider尺寸
			getSliderRect() {
			    // 获取滑块条的尺寸信息
			    // 通过nvue的dom模块，查询节点信息，其他平台使用exec
			    return new Promise((resolve) => {
			        // 如果获取的宽度 > 组件上绑定的宽度，则使用获取的
			        // 通常情况下，获取的宽度 和 组件上绑定的宽度是一样的。
			        
			       if (dom) {
					    dom.getComponentRect(this.$refs.slider, data => {
					       resolve(data.size)
					   	   //console.log('data')
					       //console.log(data)
					    });
				   }else {
						var query = uni.createSelectorQuery().in(this);
						query.select('#slider').boundingClientRect();
						query.exec(data => {
							resolve(data[0])
							   //console.log(JSON.stringify(data));
						});
				   }
			    })
			},
			
			// 点击进度条跳到进度位置
			onClick_SliderTouch(){
				// 是否禁用，如果是则返回，不继续向下执行
				if (this.canNotDo()) return

				this.oldLeftWidth = 0
				let newToucesX = sdilderPos.touchE
				//console.log('newToucesX == ' + newToucesX)
				if (newToucesX > sliderWidth) {
					// 如果点击时获取的元素screenX轴>sliderWidth进度条宽度，就减去dom获取的左边偏移距离，然后进度条拉满的情况下刚好=进度条的总宽度
					this.oldLeftWidth = newToucesX - sliderLeft
				}else {
					// 暂时保持和上方一致
					this.oldLeftWidth = newToucesX - sliderLeft
				}
				//console.log('计算前')
				//console.log(this.oldLeftWidth)
				
				// 计算进度条的偏移值
				this.oldLeftWidth = this.oldLeftWidth*this.step
				this.oldLeftWidth = this.oldLeftWidth > this.WidthValue ? this.WidthValue : this.oldLeftWidth
				this.oldLeftWidth = this.oldLeftWidth < 0 ? 0 : this.oldLeftWidth
				
				
				let current
				// 计算滑动的值
				current = this.oldLeftWidth / this.WidthValue * this.max
				// 删除小数点后的所有数字，因为只能是百分小数，如1 2 3等等，不能是如 1.2 2.656 3.72286这种
				current = parseInt(current)
				// 定义入口参数
				let event = {detail:{value:current}}
				
				//console.log('计算后')
				//console.log(current)
				
				//console.log("完成一次点击后触发的事件")
				//console.log(event.detail.value)
				
				// 完成一次点击后触发的事件
				this.change(event)
				
				// 写入触摸移动后计算的进度条值（用于触摸结束事件）
				this.posVal = current
			},
			
			// 触摸开始（将在3.3.4版本完善）
			onBlock_TouchStart(e){
				//console.log('触摸开始')
				//console.log(e.changedTouches[0])
				
				timeOutEvent = 1
				
				// 是否禁用，如果是则返回，不继续向下执行
				if (this.canNotDo()) return
				let newToucesX = this.getTouchX(e)
				sdilderPos.touchS = newToucesX
				//console.log('sta -- newToucesX')
				//console.log(newToucesX)
				
				// 是否禁用，如果是则返回，不继续向下执行
				if (this.canNotDo()) return
				// 记录手指按下时的X轴位移值
				this.oldToucesX = newToucesX
				// 记录当前进度
				this.oldLeftWidth = this.leftWidth
			},
			// 触摸移动（将在3.3.4版本完善）
			onBlock_TouchMove(e){
				//console.log('触摸移动')
				//console.log(e.changedTouches[0])
				
				// 是否禁用，如果是则返回，不继续向下执行
				if (this.canNotDo()) return
				

				// 如果手指有移动，就重置为0
				timeOutEvent = 0
				
				// 记录手指移动时的X轴位移值
				let newToucesX = this.getTouchX(e)
							
				// 滑动时进度条的值
				this.newLeftWidth = 1*(newToucesX - this.oldToucesX)*this.step + this.oldLeftWidth
				this.newLeftWidth = this.newLeftWidth > this.WidthValue ? this.WidthValue : this.newLeftWidth
				this.newLeftWidth = this.newLeftWidth < 0 ? 0 : this.newLeftWidth
				let current 
				// 计算滑动的值
				current = this.newLeftWidth / this.WidthValue * this.max
				// 删除小数点后的所有数字，因为只能是百分小数，如1 2 3等等，不能是如 1.2 2.656 3.72286这种
				current = parseInt(current)
				// 定义入口参数
				let event = {detail:{value:current}}
				
				//console.log("拖动过程中触发的事件")
				//console.log(event.detail.value)
				
				
				this.changing(event)
				// 写入触摸移动后计算的进度条值（用于触摸结束事件）
				this.posVal = current
				
			},
			// 触摸结束（将在3.3.4版本完善）
			onBlock_TouchEnd(e){
				//console.log('触摸结束')
				
				// 是否禁用，如果是则返回，不继续向下执行
				if (this.canNotDo()) return
				
				//console.log({ progress: this.posVal, value: dragVal })
				let newToucesX = this.getTouchX(e)
				sdilderPos.touchE = newToucesX
				//console.log('End -- newToucesX')
				//console.log(newToucesX)
				
				// 等于0才可以执行，否则就是点击
				if (timeOutEvent == 0){
					// 定义入口参数
					let event = {detail:{value:this.posVal}}
					// 完成一次拖动后触发的事件
					this.change(event)
				}

				// 还原状态
				timeOutEvent = 1
			},
			
			// 是否可以操作
			canNotDo() {
			    return this.disabled
			},
			
			// 获取当前手势点的X轴位移值
			getTouchX(e){
				// #ifdef APP-NVUE
				return e.changedTouches[0].screenX
				// #endif
				
				// #ifndef APP-NVUE
				return e.changedTouches[0].clientX
				// #endif
			},
			
			// 完成一次拖动后触发的事件，event.detail = {value: value}
			change(event){
				//console.log("完成一次拖动后触发的事件")
				//console.log(event.detail.value)
				this.$emit('change',event)
				//this.leftWidth = event.detail.value
				this.toUpdate(event)
			},
			// 拖动过程中触发的事件，event.detail = {value: value}
			changing(event){
				//console.log("拖动过程中触发的事件")
				//console.log(event.detail.value)
				this.$emit('changing',event)
				//this.leftWidth = event.detail.value
				this.toUpdate(event)
			},
			// 计算自定义进度条宽度,实时更新进度滑块
			toUpdate(event){
				// 获取当前进度值
				let Value = event.detail.value
				// 获取自定义进度条总宽度
				let WidthPX = this.WidthValue
				// 计算每1进度值等于多少宽度
				let ValuePX = WidthPX / 100
				// 更新当前进度(宽度) 进度值*每1进度px
				this.leftWidth = ValuePX*Value
				//console.log("this.leftWidth")
				//console.log(this.leftWidth)
				
				// 更新已缓冲完成的进度(宽度)进度值*每1进度px
				this.leftWidthBfb = ValuePX*this.sliderValueBfb
				//console.log("leftWidthBfb")
				//console.log(this.leftWidthBfb)
				
				//this.leftWidth = event.detail.value
			}
			
		}
	}
</script>

<style lang="scss" scoped>
	.slider-box-view{
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		/* #endif */
		flex-direction: column;
		padding: 0;
		justify-content: center;
		.slider{
			margin: 0;//强制更改uni默认样式
			padding: 0;//强制更改uni默认样式
		}
	}
	.slider{
		position: absolute!important;
	}
	.slider-box{
		//position: relative;
		//justify-content: center;// 注释时间：2022-0225
		
		// 2022-0313
		position: absolute!important;
	}
	
	.flex{
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		/* #endif */
	}
	.flex1{
		flex: 1;
	}
	/* 纯手工进度条 */
	.slider-box{
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		/* #endif */
		flex: 1;
		height: 8px;
		border-radius: 5px;
		//background-color: #000;
		flex-direction: row;
		flex-wrap: nowrap;
		align-items: center;
		//position: relative;
		.left-slider,.right-slider,
		.left,.right,.slider-huanchong,
		.left-slider-huanchong{
			height: 3px;
			//border-radius: 3rpx;
		}
		.left-slider,.left,.left-slider-huanchong{
			border-top-left-radius: 5px;
			border-bottom-left-radius: 5px;
		}
		.right-slider,.right{
			border-top-right-radius: 5px;
			border-bottom-right-radius: 5px;
		}
		.left-slider,.right-slider{}
		.left-slider{
			//height: 12px!important;
			//width: 100px;
			.left{
				flex: 1;
				background-color: #00d0d3;
				//position: relative;
			}
			// .block-box-line{
			// 	right: 0;
			// 	position: absolute;
			// 	width: 12px;//使用绝对像素，方便计算小圆点位置
			// 	height: 12px;
			// 	border-radius: 6px;
			// 	background-color: #00f8ff;
			// }
		}
		.right-slider{
			//width: 55px;
			.right{
				flex: 1;
				background-color: rgba(255, 255, 255, 0.65);
				//background-color: #007AFF;
			}
		}
		.block-box{
			//left: 100px;
			position: absolute;
			width: 8px;//使用绝对像素，方便计算小圆点位置
			height: 8px;
			border-radius: 4px;
			background-color: #00f8ff;
		}
		.left-slider-huanchong{
			position: absolute;
			//background-color: rgba(255, 255, 255, 0.65);
			.slider-huanchong{
				//width: 120px;
				//background-color: rgba(255, 255, 255, 0.85);
				//background-color: #00f8ff;
				//background-color: rgba(0,248,255,0.35);
			}
		}
	}
	
	// 这里就不改成 &__ 去连接了
	// 防止上方嵌套样式打包时丢失，不生效
	.slider-box{
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		/* #endif */
		flex: 1;
		height: 8px;
		border-radius: 5px;
		//background-color: #000;
		flex-direction: row;
		flex-wrap: nowrap;
		align-items: center;
		//position: relative;
	}
	
	.slider-box .left-slider,
	.slider-box .right-slider,
	.slider-box .slider-huanchong,
	.slider-box .left-slider-huanchong,
	.slider-box .left,
	.slider-box .right{
		height: 3px;
	}
	
	.slider-box .left-slider,
	.slider-box .left,
	.slider-box .left-slider-huanchong{
		border-top-left-radius: 5px;
		border-bottom-left-radius: 5px;
		
	}
	
	.slider-box .right-slider,
	.slider-box .right{
		border-top-right-radius: 5px;
		border-bottom-right-radius: 5px;
	}
	
	.slider-box .left-slider .left{
		flex: 1;
		//background-color: #00d0d3;
		//position: relative;
	}
	
	.slider-box .right-slider .right{
		flex: 1;
		background-color: rgba(255, 255, 255, 0.65);
	}
	
	.slider-box .block-box{
		//left: 100px;
		position: absolute;
		width: 8px;//使用绝对像素，方便计算小圆点位置
		height: 8px;
		border-radius: 4px;
		background-color: #00f8ff;
	}
	.slider-box .left-slider-huanchong{
		position: absolute;
		//background-color: rgba(255, 255, 255, 0.65);
	}
	
	.slider-box .slider-huanchong{
		//width: 120px;
		//background-color: rgba(255, 255, 255, 0.85);
		//background-color: #00f8ff;
		//background-color: rgba(0,248,255,0.35);
	}
</style>
